package br.unb.midialab.evo.birds.model;

import processing.core.PApplet;
import processing.core.PFont;

public class Bird {

	// Properties
	float offsetX, offsetY, offsetZ;
	float w, h;
	int bodyFill;
	int wingFill;
	float ang = 0, ang2 = 0, ang3 = 0, ang4 = 0;
	float radiusX = 120, radiusY = 200, radiusZ = 700;
	float rotX = 15, rotY = 10, rotZ = 5;
	float flapSpeed = 0.4f;
	float rotSpeed = 0.1f;
	float initialFontSize;
	float fontSize;
	PFont font;
	PApplet parent;
	String[] text;
	private int index = 99;


	// Constructors
	Bird() throws Exception{
		throw new Exception ("Deprecated, use Bird(float offsetX, float offsetY, float offsetZ, float w, float h, PApplet parent) instead.");
	}

	public Bird(float offsetX, float offsetY, float offsetZ, 
			float w, float h, PApplet parent, String[] text){
		this.offsetX = offsetX;
		this.offsetY = offsetY;
		this.offsetZ = offsetZ;
		this.h = h;
		this.w = w;
		this.initialFontSize = 100;
		this.parent = parent;
		this.text = text;
		bodyFill = parent.color(255);
		wingFill = parent.color(0);
		font = parent.loadFont("../data/CourierNew36.vlw"); 
		parent.textFont(font); 
		
	}

	public void setFontSize() {
		initialFontSize = 100;
		parent.textSize(initialFontSize);
		while (parent.textAscent()>h/2) {
			initialFontSize -= 1;
			parent.textSize(initialFontSize);
		}
	}

	public void setFlight(float radiusX, float radiusY, float radiusZ, 
			float rotX, float rotY, float rotZ){
		this.radiusX = radiusX;
		this.radiusY = radiusY;
		this.radiusZ = radiusZ;

		this.rotX = rotX;
		this.rotY = rotY;
		this.rotZ = rotZ;
	}

	public void setWingSpeed(float flapSpeed){
		this.flapSpeed = flapSpeed;
	}

	public void setRotSpeed(float rotSpeed){
		this.rotSpeed = rotSpeed;
	}

	public void fly() {
		float ascent;
		parent.pushMatrix();
		float px, py, pz;

		//setFontSize();

		// Flight
		px = parent.sin(parent.radians(ang3)) * radiusX;
		py = parent.cos(parent.radians(ang3)) * radiusY;
		pz = parent.sin(parent.radians(ang4)) * radiusZ;

		parent.translate(parent.width/2 + offsetX + px, parent.height/2 + offsetY+py,  0 + offsetZ+pz);

		parent.rotateX(parent.sin(parent.radians(ang2)) * rotX);
		parent.rotateY(parent.sin(parent.radians(ang2)) * rotY);
		parent.rotateZ(parent.sin(parent.radians(ang2)) * rotZ);

		parent.rotateZ(-parent.PI/2);
		// Body
		parent.fill(bodyFill);
		//    box(w/5, h, w/5);
		//drawCylinder(8, w/5, h);
		// Left wing
		parent.fill(wingFill);
		parent.pushMatrix();
		parent.rotateY(parent.sin(parent.radians(ang)) * 20);
		parent.text(text[0], 0 , 0); 
		//rect(0, 0, w, h);
		parent.popMatrix();

		// Right wing
		parent.pushMatrix();
		parent.rotateY(parent.sin(parent.radians(ang)) * -20);
		//rect(-w, -h/2, w, h);
		parent.text(text[1], 0, 0); 
		parent.popMatrix();

		parent.rotateZ(parent.PI/2);
		// Wing flap
		ang += flapSpeed;
		if (ang > 0) {
			flapSpeed*=-1;
		} 
		if (ang < -3) {
			flapSpeed*=-1;
		}

		// Ang's run trig functions
		ang2 += rotSpeed;
		ang3 += 1.25f;
		ang4 += 0.55f;
		parent.popMatrix();
	}

	public void drawCylinder(int sides, float r, float h)
	{
		parent.rotateX(parent.PI/2);
		float angle = 360 / sides;
		float halfHeight = h / 2;
		// draw top shape
		parent.beginShape();
		for (int i = 0; i < sides; i++) {
			float x = parent.cos( parent.radians( i * angle ) ) * r;
			float y = parent.sin( parent.radians( i * angle ) ) * r;
			parent.vertex( x, y, -halfHeight );    
		}
		parent.endShape(parent.CLOSE);
		// draw bottom shape
		parent.beginShape();
		for (int i = 0; i < sides; i++) {
			float x = parent.cos( parent.radians( i * angle ) ) * r;
			float y = parent.sin( parent.radians( i * angle ) ) * r;
			parent.vertex( x, y, halfHeight );    
		}
		parent.endShape(parent.CLOSE);

		parent.beginShape(parent.TRIANGLE_STRIP);
		for (int i = 0; i < sides + 1; i++) {
			float x = parent.cos( parent.radians( i * angle ) ) * r;
			float y = parent.sin( parent.radians( i * angle ) ) * r;
			parent.vertex( x, y, halfHeight);
			parent.vertex( x, y, -halfHeight);    
		}
		parent.endShape(parent.CLOSE);
		parent.rotateX(-parent.PI/2);
	}
	
	@Override public boolean equals(Object aThat) {
	    //check for self-comparison
	    if ( this == aThat ) return true;

	    //use instanceof instead of getClass here for two reasons
	    //1. if need be, it can match any supertype, and not just one class;
	    //2. it renders an explict check for "that == null" redundant, since
	    //it does the check for null already - "null instanceof [type]" always
	    //returns false. (See Effective Java by Joshua Bloch.)
	    if ( !(aThat instanceof Bird) ) return false;
	    //Alternative to the above line :
	    //if ( aThat == null || aThat.getClass() != this.getClass() ) return false;

	    //cast to native object is now safe
	    Bird that = (Bird)aThat;

	    //now a proper field-by-field evaluation can be made
	    return getText().equals(that.getText());
	  }
	
public String getText() {
	return this.text[0].concat(this.text[1]);
}

public void setIndex(int index) {
	this.index = index;
}

public int getIndex() {
	return index;
}

}
